#pragma once

#include "misc/string_ext.hpp"
#include "rewine/IExport.hpp"
#include "rewine/IImage.hpp"
#include "rewine/impl/CPeImport.hpp"

#include <memory>
#include <string>
#include <map>
#include <utility>

namespace rewine
{

class Loader;
class CExport;

/*
class resolving_key_t {
private:

    std::string m_dll;
    std::string m_symbol;

public:

    resolving_key_t(std::string dll, std::string symbol)
            : m_dll(std::move(dll)), m_symbol(std::move(symbol)) {
        lower_string(m_dll);
    }

    resolving_key_t(const resolving_key_t& rhs)
            : resolving_key_t(rhs.m_dll, rhs.m_symbol) {
    }

    resolving_key_t(resolving_key_t&& rhs) noexcept
            : m_dll(std::move(rhs.m_dll)), m_symbol(std::move(rhs.m_symbol)) {
        lower_string(m_dll);
    }

public:

    static resolving_key_t genKey(const std::string& dll, const std::string& symbol) {
        return resolving_key_t(dll, symbol);
    }

    static resolving_key_t genKey(const std::string& dll, int ordinal) {
        return resolving_key_t(dll, std::string("#") + std::to_string(ordinal));
    }

 public:

    std::string getDll() const {
        return m_dll;
    }

    std::string getSymbol() const {
        return m_symbol;
    }

    bool operator ==(const resolving_key_t& rhs) const {
        return (m_dll == rhs.m_dll)
            && (m_symbol == rhs.m_symbol)
            ;
    }

    bool operator <(const resolving_key_t& rhs) const {
        if (m_dll < rhs.m_dll) return true;
        if (m_symbol < rhs.m_symbol) return true;
        return false;
    }

};
*/

class SymbolResolver {
public:

    bool resolveAndBind(
        IImage *pImage, const std::string& dll, const std::string& symbol, uint16_t hint,
        ValueSynchronizer& valueSynchronizer, bool bSyncNow) const;
};

} // namespace rewine
